#!/bin/sh /etc/rc.common
START=55

include /lib/network
include /usr/lib/gargoyle_firewall_util

backup_script_dir="/tmp/bw_backup"
backup_script="$backup_script_dir/do_bw_backup.sh"
tmp_cron="/tmp/tmp.cron"
download_table=filter
download_chain=bw_ingress
upload_table=mangle
upload_chain=bw_egress

bw_restore()
{
	bw_id="$1"
	backup_to_tmp="$2"
	
	if [ -e "/usr/data/bwmon/$bw_id.bw" ] ; then
		bw_set -i "$bw_id" -h -f /usr/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/tmp/data/bwmon/$bw_id.bw" ] ; then
		bw_set -i "$bw_id" -h -f /tmp/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/usr/data/bwmon/$bw_id" ] ; then
		bw_convert "/usr/data/bwmon/$bw_id" "/usr/data/bwmon/$bw_id.bw"
		rm "/usr/data/bwmon/$bw_id"
		bw_set -i "$bw_id" -h -f /usr/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/tmp/data/bwmon/$bw_id" ] ; then
		bw_convert "/tmp/data/bwmon/$bw_id" "/usr/data/bwmon/$bw_id.bw"
		rm "/tmp/data/bwmon/$bw_id"
		bw_set -i "$bw_id" -h -f /tmp/data/bwmon/$bw_id.bw >/dev/null 2>&1
	fi

	if [ -e "$tmp_cron" ] ; then
		if [ "$backup_to_tmp" = "1" ] ; then
			echo "bw_get -i \"$bw_id\" -h -f \"/tmp/data/bwmon/$bw_id.bw\" >/dev/null 2>&1" >> "$backup_script"
		else
			echo "bw_get -i \"$bw_id\" -h -f \"/usr/data/bwmon/$bw_id.bw\" >/dev/null 2>&1" >> "$backup_script"
		fi
	fi
}

update_cron()
{
	old_md5=$(md5sum /etc/crontabs/root)
	old_md5=${old_md5% *}
	new_md5=$(md5sum "$tmp_cron")
	new_md5=${new_md5% *}
	if [ "$old_md5" = "$new_md5" ] ; then
		rm "$tmp_cron"
	else
		mv "$tmp_cron" /etc/crontabs/root
		if pidof crond > /dev/null 2>&1; then
			/etc/init.d/cron restart
		fi
	fi
}


start()
{

	define_wan_if
	wan_ip=""
	bw_if="$wan_if"
	if [ -z "$bw_if" ] ; then
		network_get_device bw_if lan || \
			bw_if=$(uci -q get network.lan.ifname)
	else
		network_get_ipaddr wan_ip wan
	fi
	



	if [ ! -d /tmp/data/bwmon ] ; then
		rm -rf /tmp/data/bwmon
		mkdir -p /tmp/data/bwmon
 	fi
	if [ ! -d /usr/data/bwmon ] ; then 
		rm -rf /usr/data/bwmon
		mkdir -p /usr/data/bwmon
	fi

	delete_chain_from_table $download_table $download_chain
	iptables -t $download_table -N $download_chain
	iptables -t $download_table -I INPUT $filter_insert_index  -i $bw_if -j $download_chain
	iptables -t $download_table -I FORWARD $filter_insert_index -i $bw_if -j $download_chain
	ip6tables -t $download_table -N $download_chain
	ip6tables -t $download_table -I INPUT $filter_insert_index  -i $bw_if -j $download_chain
	ip6tables -t $download_table -I FORWARD $filter_insert_index -i $bw_if -j $download_chain


	
	delete_chain_from_table $upload_table $upload_chain
	iptables -t $upload_table -N $upload_chain
	iptables -t $upload_table -A POSTROUTING -o $bw_if -j $upload_chain
	ip6tables -t $upload_table -N $upload_chain
	ip6tables -t $upload_table -A POSTROUTING -o $bw_if -j $upload_chain
	

	network_get_subnet lan_ip lan

	# code to help filter out bogons on distribution monitors, 
	# which make up really small amount of bandwidth, but screw up monitoring

	iptables -t $upload_table -A $upload_chain                                    -j CONNMARK --set-mark 0x0/0xFF000000
	iptables -t $upload_table -A $upload_chain -s $lan_ip                         -j CONNMARK --set-mark 0x0F000000/0xFF000000
	iptables -t $upload_table -A $upload_chain -s $wan_ip                         -j CONNMARK --set-mark 0x0F000000/0xFF000000
	iptables -t $upload_table -A $upload_chain -m connmark --mark 0x0/0x0F000000  -j RETURN
	iptables -t $upload_table -A $upload_chain                                    -j CONNMARK --set-mark 0x0/0xFF000000
	

	iptables -t $download_table -A $download_chain                                    -j CONNMARK --set-mark 0x0/0xFF000000
	iptables -t $download_table -A $download_chain -d $lan_ip                         -j CONNMARK --set-mark 0x0F000000/0xFF000000
	iptables -t $download_table -A $download_chain -d $wan_ip                         -j CONNMARK --set-mark 0x0F000000/0xFF000000
	iptables -t $download_table -A $download_chain -m connmark --mark 0x0/0x0F000000  -j RETURN
	iptables -t $download_table -A $download_chain                                    -j CONNMARK --set-mark 0x0/0xFF000000


	minute_s=60
	hour_s=3600
	day_s=86400

	total1_interval=2
	total1_num_intervals=449
	total1_reset_time=2

	total2_interval="minute"
	total2_num_intervals=359

	total3_interval=$((3*$minute_s))
	total3_num_intervals=479
	total3_reset_time=$((3*$minute_s))

	total4_interval=$((2*$hour_s))
	total4_num_intervals=359
	total4_reset_time=$((2*$hour_s))
	
	total5_interval="day"
	total5_num_intervals=365

	bdist0_interval=$total1_interval
	bdist0_num_intervals=$total1_num_intervals
	bdist0_reset_time=$total1_reset_time

	bdist1_interval="minute"
	bdist1_num_intervals=15

	bdist2_interval=$((15*$minute_s))
	bdist2_num_intervals=24
	bdist2_reset_time=$((15*$minute_s))

	bdist3_interval="hour"
	bdist3_num_intervals=24

	bdist4_interval="day"
	bdist4_num_intervals=31

	bdist5_interval="month"
	bdist5_num_intervals=12

	custom_reset_time=$(uci get gargoyle.bandwidth_display.month_reset_day 2>/dev/null)
	if [ -z "$custom_reset_time" ] ; then
		custom_reset_time=0
	fi
	bdist6_interval="month"
	bdist6_num_intervals=12
	bdist6_reset_time=$(($custom_reset_time*$day_s))

	ids=""


	high_res_15m=$(uci get gargoyle.bandwidth_display.high_res_15m 2>/dev/null)
	#echo "high res 15m = $high_res_15m"
	if [ "$high_res_15m" = "1" ] ; then
		n=0
		bdist_interval=$(eval "echo \$bdist"$n"_interval")
		bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
		bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
		if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi
		if [ -n "$lan_ip" ] ; then
			iptables -t $download_table -A $download_chain -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ip6tables -t $download_table -A $download_chain -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ip6tables -t $upload_table   -A $upload_chain   -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi
	else
		rm -rf /tmp/data/bwmon/bdist0*
		rm -rf /tmp/data/bwmon/qos0*
	fi
	
	mon_nums="1 2 3 4 5"
	custom_bwmon=$(uci get gargoyle.bandwidth_display.custom_bwmon_enable 2>/dev/null)
	if [ "$custom_bwmon" = "1" ] ; then
		mon_nums="$mon_nums 6"
	fi
	for n in $mon_nums ; do
		total_interval=$(eval "echo \$total"$n"_interval")
		total_num_intervals=$(eval "echo \$total"$n"_num_intervals")
		total_reset_time=$(eval "echo \$total"$n"_reset_time")
		if [ -n "$total_reset_time" ] ; then total_reset_time="--reset_time $total_reset_time" ; fi

		bdist_interval=$(eval "echo \$bdist"$n"_interval")
		bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
		bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
		if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

		if [ $n -lt 6 ] ; then
			iptables -t $download_table -A $download_chain -m bandwidth --id "total"$n"-download-$total_interval-$total_num_intervals" --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time
			ip6tables -t $download_table -A $download_chain -m bandwidth --id "total"$n"-download-$total_interval-$total_num_intervals" --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time
			iptables -t $upload_table   -A $upload_chain   -m bandwidth --id "total"$n"-upload-$total_interval-$total_num_intervals"   --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time
			ip6tables -t $upload_table   -A $upload_chain   -m bandwidth --id "total"$n"-upload-$total_interval-$total_num_intervals"   --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time

			next_ids="total"$n"-download-$total_interval-$total_num_intervals total"$n"-upload-$total_interval-$total_num_intervals"
			if [ -z "$ids" ] ; then
				ids="$next_ids"
			else
				ids="$ids $next_ids"
			fi
		fi

		if [ -n "$lan_ip" ] ; then
			iptables -t $download_table -A $download_chain -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ip6tables -t $download_table -A $download_chain -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ip6tables -t $upload_table   -A $upload_chain   -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="$ids bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi

	done

	if [ "$high_res_15m" = "1" ] ; then
		mon_nums="0 $mon_nums"
	fi
	qos_enabled=$(ls /etc/rc.d/*qos_gargoyle 2>/dev/null)
	if [ -n "$qos_enabled" ] && [ -e /etc/qos_class_marks ] ; then
		qos_table="mangle"
		qos_upload_chain="qos_egress"
		qos_download_chain="qos_ingress"

		upload_data=$(awk ' { if($1 == "upload"){print "up-"$2":"$3"/"$4};}' /etc/qos_class_marks )
		download_data=$(awk ' { if($1 == "download"){print "down-"$2":"$3"/"$4};}' /etc/qos_class_marks )

		for upload_info in $upload_data ; do
			mark=$(echo $upload_info | awk ' BEGIN { FS=":";} { print $2; }')
			class=$(echo $upload_info | awk ' BEGIN { FS=":";} { print $1; }')
			for n in $mon_nums ; do
				bdist_interval=$(eval "echo \$bdist"$n"_interval")
				bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
				bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
				if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

				iptables -t $upload_table -A $upload_chain -m connmark --mark $mark -m bandwidth --id "qos"$n"-$class-$bdist_interval-$bdist_num_intervals" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
				ids="$ids qos"$n"-$class-$bdist_interval-$bdist_num_intervals"
			done
		done
		
		
		for download_info in $download_data ; do
			mark=$(echo $download_info | awk ' BEGIN { FS=":";} { print $2; }')
			class=$(echo $download_info | awk ' BEGIN { FS=":";} { print $1; }')
			for n in $mon_nums ; do
				bdist_interval=$(eval "echo \$bdist"$n"_interval")
				bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
				bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
				if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

				iptables -t $download_table -A $download_chain -m connmark --mark $mark -m bandwidth --id "qos"$n"-$class-$bdist_interval-$bdist_num_intervals" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
				ids="$ids qos"$n"-$class-$bdist_interval-$bdist_num_intervals"
			done
		done
	fi




	touch /etc/crontabs/root
	grep -v "$backup_script" /etc/crontabs/root > "$tmp_cron"
	echo "0 0,4,8,12,16,20 * * * $backup_script" >> "$tmp_cron"
	
	mkdir -p "$backup_script_dir"
	echo "#!/bin/sh"          > "$backup_script"
	echo "touch /etc/banner" >> "$backup_script"
	chmod 700 "$backup_script"
	

	for i in $ids ; do
		is_total123=$(echo "$i" | egrep "total[123]")
		is_bdist123=$(echo "$i" | egrep "bdist[0123]")
		is_qos123=$(echo "$i" | egrep "qos[0123]")
		if [ -n "$is_total123" ] || [ -n "$is_bdist123" ] || [ -n "$is_qos123" ]  ; then
			bw_restore "$i" 1
		else
			bw_restore "$i" 0
		fi
	done

	update_cron 
}

stop()
{
	#check that we aren't already stopped before backing up data
	have_up=$(iptables   -t "$upload_table"   -L "$upload_chain" 2>/dev/null)
	have_down=$(iptables -t "$download_table" -L "$download_chain" 2>/dev/null)
	have_up6=$(ip6tables   -t "$upload_table"   -L "$upload_chain" 2>/dev/null)
	have_down6=$(ip6tables -t "$download_table" -L "$download_chain" 2>/dev/null)
	if [ -n "$have_up" ] || [ -n "$have_down" ] || [ -n "$have_up6" ] || [ -n "$have_down6" ] ; then
		sh "$backup_script" 2>/dev/null
		rm -rf "$backup_script"

		touch /etc/crontabs/root
		grep -v "$backup_script" /etc/crontabs/root > "$tmp_cron"
		update_cron
	
		if [ -n "$have_up" ] || [ -n "$have_up6" ] ; then
			delete_chain_from_table $upload_table $upload_chain >/dev/null 2>&1
		fi
		if [ -n "$have_down" ] || [ -n "$have_down6" ] ; then
			delete_chain_from_table $download_table $download_chain >/dev/null 2>&1
		fi
	fi
}

restart()
{
	stop
	start
}

boot()
{
	#Do nothing during init.  Start is called by hotplug.
	return
}
